﻿
//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////

#include "PickFilterDlg.h"
#include "IDock.h"
#include "GbmpNew.h"
#include "ICategory.h"
#include "IUiManager.h"
#include "IMainWindow.h"
#include "UniIdentity.h"
#include "IPickTarget.h"
#include "IPickFilter.h"
#include "IDockManager.h"
#include "IPickContext.h"
#include "ICategoryLibrary.h"
#include "IUiDocumentViewManager.h"
#include "IPickNodeReferenceAction.h"

#include "qevent.h"
#include "QTreeWidget.h"
#include "BaseTreeDlg.h"
#include "PickSnapCommandIds.h"
#include "CmdPickModuleEntry.h"
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

using namespace gcmp;
using namespace Sample;

#pragma region 初始化
PickFilterDlg::PickFilterDlg(QWidget *parent)
    : BaseTreeDlg(parent)
{
    InitQTree();
    SetPickMethod(PickMethod::PickNodeReferenceAction);
}

PickFilterDlg::~PickFilterDlg(void){}

#pragma endregion 初始化

#pragma region 和GDMP GUI接口相关的初始化和单例获取
PickFilterDlg* PickFilterDlg::Create()
{
    if (PickFilterDlg* pPickDlg = Get())
    {
        return pPickDlg;
    }
    IUiManager *pUiManager = IUiManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiManager, L"pUiManager为空",L"GDMP",L"2023-12-30");

    IDockManager * pDockManager = pUiManager->GetDockManager();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDockManager, L"pDockManager为空",L"GDMP",L"2023-12-30");

    IUiDocumentViewManager * pUiDocViewMgr = IUiDocumentViewManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pUiDocViewMgr, L"pUiDocViewMgr为空",L"GDMP",L"2023-12-30");

    OwnerPtr<IDock> opDock = pDockManager->CreateDock(ID_DOCK_PICK_FILTER, GBMP_TR(L"拾取过滤"));
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opDock, L"opDock为空",L"GDMP",L"2023-12-30");

    OwnerPtr<PickFilterDlg> opPickDlg = NEW_AS_OWNER_PTR(PickFilterDlg);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(opPickDlg, L"opPickDlg为空",L"GDMP",L"2023-12-30");
    opPickDlg->setMinimumWidth(200);
    opDock->SetWidget(TransferOwnership(opPickDlg));

    pDockManager->AddDock(TransferOwnership(opDock), DockArea::Right, DockOrientation::Vertical);

    return Get();
}

void Sample::PickFilterDlg::ShowDock()
{
    IDock* pDock = GetDock(ID_DOCK_PICK_FILTER);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDock, L"pDock为空",L"GDMP",L"2023-12-30");
    pDock->Show();
}

void Sample::PickFilterDlg::HideDock()
{
    IDock* pDock = GetDock(ID_DOCK_PICK_FILTER);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pDock, L"pDock为空",L"GDMP",L"2023-12-30");
    pDock->Hide();
}

PickFilterDlg * PickFilterDlg::Get()
{
    IDock* pDock = GetDock(ID_DOCK_PICK_FILTER);
    if (!pDock)
    {
        return nullptr;
    }

    PickFilterDlg* dlg = dynamic_cast<PickFilterDlg*>(pDock->GetWidget());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(dlg, L"dlg为空",L"GDMP",L"2023-12-30");
    return dlg;
}
#pragma endregion 和GDMP GUI接口相关的初始化和单例获取

#pragma region 和拾取相关的逻辑
void PickFilterDlg::InitQTree()
{
    m_pQTreeWidget->clear();

    std::map<std::wstring, std::function<void(IPickContext*, bool)>> pickContextMap = {
        {L"SetSelectByFaceInteriorEnabled", [](IPickContext* pPickContext, bool flag)->void {pPickContext->SetSelectByFaceInteriorEnabled(flag); }},
        {L"SetAllowPickingHighlightOnlyGraphicsNode", [](IPickContext* pPickContext, bool flag)->void {pPickContext->SetAllowPickingHighlightOnlyGraphicsNode(flag); }}
    };
    m_pickContextMap.insert(pickContextMap.begin(), pickContextMap.end());

    std::map<std::wstring, std::function<void(IPickTarget*, bool)>> pickTargetMap = {
        { L"EnableGraphicsElementShape", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableGraphicsElementShape() : pPickTarget->DisableGraphicsElementShape(); } },
        { L"EnableFace", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableFace() : pPickTarget->DisableFace(); } },
        { L"EnableCurve", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableCurve() : pPickTarget->DisableCurve(); } },
        { L"EnablePoint", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnablePoint() : pPickTarget->DisablePoint(); } },
        { L"EnableEdge", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableEdge() : pPickTarget->DisableEdge(); } },
        { L"EnableText", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableText() : pPickTarget->DisableText(); } },
        { L"EnableEndPoint", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableEndPoint() : pPickTarget->DisableEndPoint(); } },
        { L"EnableCenterPoint", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableCenterPoint() : pPickTarget->DisableCenterPoint(); } },
        { L"EnableDocReference", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableDocReference() : pPickTarget->DisableDocReference(); } },
        { L"EnableMeshTriangle", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableMeshTriangle() : pPickTarget->DisableMeshTriangle(); } },
        { L"EnableSegmentOfPolyCurve", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableSegmentOfPolyCurve() : pPickTarget->DisableSegmentOfPolyCurve(); } },
        { L"EnableSegmentOfPolyCurve3d", [](IPickTarget* pPickTarget, bool flag)->void {flag ? pPickTarget->EnableSegmentOfPolyCurve3d() : pPickTarget->DisableSegmentOfPolyCurve3d(); } }
    };
    m_pickTargetMap.insert(pickTargetMap.begin(), pickTargetMap.end());

    std::map<std::wstring, std::function<void(PickNodeReferenceOption&, bool)>> pickNodeReferenceOptionMap = {
        { L"SetIsMoveAllowed", [](PickNodeReferenceOption& pickOption, bool flag)->void {pickOption.SetIsMoveAllowed(flag); } },
        { L"SetIsPickingHighlightOnlyGraphicsNodeAllowed", [](PickNodeReferenceOption& pickOption, bool flag)->void {pickOption.SetIsPickingHighlightOnlyGraphicsNodeAllowed(flag); } },
        { L"SetMultiSelect", [](PickNodeReferenceOption& pickOption, bool flag)->void {pickOption.SetMultiSelect(flag); } },
        { L"SetPickElementShapeHandle", [](PickNodeReferenceOption& pickOption, bool flag)->void {pickOption.SetPickElementShapeHandle(flag); } }
    };
    m_pickNodeReferenceOptionMap.insert(pickNodeReferenceOptionMap.begin(), pickNodeReferenceOptionMap.end());

    std::map<std::wstring, std::function<void(gcmp::PickNodeReferenceExchangeData&, bool)>> pickNodeReferenceExchangeDataMap = {
        { L"bSingleSelectMode", [](PickNodeReferenceExchangeData& pickExData, bool flag)->void {pickExData.bSingleSelectMode = flag; } },
        { L"bMouseOnWorkPlane", [](PickNodeReferenceExchangeData& pickExData, bool flag)->void {pickExData.bMouseOnWorkPlane = flag; } }
    };
    m_pickNodeReferenceExchangeDataMap.insert(pickNodeReferenceExchangeDataMap.begin(), pickNodeReferenceExchangeDataMap.end());

    const bool sortingEnabled = m_pQTreeWidget->isSortingEnabled();
    m_pQTreeWidget->setSortingEnabled(false);

    QTreeWidgetItem *topLevelItem = NEW_AS_QT(QTreeWidgetItem, m_pQTreeWidget);
    DBG_WARN_AND_RETURN_VOID_UNLESS(topLevelItem, L"topLevelItem为空",L"GDMP",L"2023-12-30");
    topLevelItem->setText(0, QString::fromStdWString(GBMP_TR(L"拾取过滤")));

    {
        m_pickContextNodeGroup = NEW_AS_QT(QTreeWidgetItem, topLevelItem);
        m_pickContextNodeGroup->setCheckState(0, Qt::Checked);
        m_pickContextNodeGroup->setText(0, QString::fromStdWString(GBMP_TR(L"IPickContext")));

        for (auto itor : m_pickContextMap)
        {
            QTreeWidgetItem *curItem = NEW_AS_QT(QTreeWidgetItem, m_pickContextNodeGroup);
            DBG_WARN_AND_RETURN_VOID_UNLESS(curItem, L"curItem为空",L"GDMP",L"2023-12-30");
            curItem->setCheckState(0, Qt::Checked);
            curItem->setText(0, QString::fromStdWString(GBMP_TR(itor.first)));
            m_pickContextNodeGroup->addChild(curItem);
        }
    }

    {
        m_pickTargetNodeGroup = NEW_AS_QT(QTreeWidgetItem, topLevelItem);
        m_pickTargetNodeGroup->setCheckState(0, Qt::Checked);
        m_pickTargetNodeGroup->setText(0, QString::fromStdWString(GBMP_TR(L"IPickTarget")));

        for (auto itor : m_pickTargetMap)
        {
            QTreeWidgetItem *curItem = NEW_AS_QT(QTreeWidgetItem, m_pickTargetNodeGroup);
            DBG_WARN_AND_RETURN_VOID_UNLESS(curItem, L"curItem为空",L"GDMP",L"2023-12-30");
            curItem->setCheckState(0, Qt::Checked);
            curItem->setText(0, QString::fromStdWString(GBMP_TR(itor.first)));
            m_pickTargetNodeGroup->addChild(curItem);
        }
    }

    {
        m_pickNodeReferenceOptionNodeGroup = NEW_AS_QT(QTreeWidgetItem, topLevelItem);
        m_pickNodeReferenceOptionNodeGroup->setCheckState(0, Qt::Checked);
        m_pickNodeReferenceOptionNodeGroup->setText(0, QString::fromStdWString(GBMP_TR(L"PickNodeReferenceOption")));

        for (auto itor : m_pickNodeReferenceOptionMap)
        {
            QTreeWidgetItem *curItem = NEW_AS_QT(QTreeWidgetItem, m_pickNodeReferenceOptionNodeGroup);
            DBG_WARN_AND_RETURN_VOID_UNLESS(curItem, L"curItem为空",L"GDMP",L"2023-12-30");
            curItem->setCheckState(0, Qt::Checked);
            curItem->setText(0, QString::fromStdWString(GBMP_TR(itor.first)));
            m_pickNodeReferenceOptionNodeGroup->addChild(curItem);
        }
    }

    {
        m_pickNodeReferenceExchangeDataNodeGroup = NEW_AS_QT(QTreeWidgetItem, topLevelItem);
        m_pickNodeReferenceExchangeDataNodeGroup->setCheckState(0, Qt::Checked);
        m_pickNodeReferenceExchangeDataNodeGroup->setText(0, QString::fromStdWString(GBMP_TR(L"PickNodeReferenceExchangeData")));

        for (auto itor : m_pickNodeReferenceExchangeDataMap)
        {
            QTreeWidgetItem *curItem = NEW_AS_QT(QTreeWidgetItem, m_pickNodeReferenceExchangeDataNodeGroup);
            DBG_WARN_AND_RETURN_VOID_UNLESS(curItem, L"curItem为空",L"GDMP",L"2023-12-30");
            curItem->setCheckState(0, Qt::Checked);
            curItem->setText(0, QString::fromStdWString(GBMP_TR(itor.first)));
            m_pickNodeReferenceExchangeDataNodeGroup->addChild(curItem);
        }
    }

    QTreeWidgetItem* pPickFilterNodeGroup = NEW_AS_QT(QTreeWidgetItem, topLevelItem);
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPickFilterNodeGroup, L"pPickFilterNodeGroup为空",L"GDMP",L"2023-12-30");
    pPickFilterNodeGroup->setCheckState(0, Qt::Checked);
    pPickFilterNodeGroup->setText(0, QString::fromStdWString(GBMP_TR(L"IPickFilter")));
    {
        m_allowElementItem = NEW_AS_QT(QTreeWidgetItem, pPickFilterNodeGroup);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_allowElementItem, L"m_allowElementItem为空",L"GDMP",L"2023-12-30");
        m_allowElementItem->setCheckState(0, Qt::Checked);
        m_allowElementItem->setText(0, QString::fromStdWString(GBMP_TR(L"AllowElement")));
        m_pickNodeReferenceExchangeDataNodeGroup->addChild(m_allowElementItem);

        m_allowGraphicsNodeItem = NEW_AS_QT(QTreeWidgetItem, pPickFilterNodeGroup);
        DBG_WARN_AND_RETURN_VOID_UNLESS(m_allowGraphicsNodeItem, L"m_allowGraphicsNodeItem为空",L"GDMP",L"2023-12-30");
        m_allowGraphicsNodeItem->setCheckState(0, Qt::Checked);
        m_allowGraphicsNodeItem->setText(0, QString::fromStdWString(GBMP_TR(L"AllowGraphicsNode")));
        m_pickNodeReferenceExchangeDataNodeGroup->addChild(m_allowGraphicsNodeItem);
    }

    m_pQTreeWidget->setSortingEnabled(sortingEnabled);
    m_pQTreeWidget->expandAll();
}

bool PickFilterDlg::AllowGraphicsNode()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_allowGraphicsNodeItem, L"m_allowGraphicsNodeItem为空",L"GDMP",L"2023-12-30");
    return m_allowGraphicsNodeItem->checkState(0) == Qt::Checked;
}

bool PickFilterDlg::AllowElement()
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(m_allowElementItem, L"m_allowElementItem为空",L"GDMP",L"2023-12-30");
    return m_allowElementItem->checkState(0) == Qt::Checked;
}

void Sample::PickFilterDlg::SetPickContext(gcmp::IPickContext * pPickContext)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPickContext, L"pPickContext为空",L"GDMP",L"2023-12-30");
    for (int i = 0; i < m_pickContextNodeGroup->childCount(); i++)
    {
        QTreeWidgetItem* item = m_pickContextNodeGroup->child(i);
        DBG_WARN_AND_RETURN_VOID_UNLESS(item, L"item为空",L"GDMP",L"2023-12-30");
        std::wstring itemText = item->text(0).toStdWString();
        auto itor = m_pickContextMap.find(itemText);
        if (itor != m_pickContextMap.end())
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(itor->second, L"itor为空",L"GDMP",L"2023-12-30");
            itor->second(pPickContext, item->checkState(0) == Qt::Checked);
        }
    }
}

void Sample::PickFilterDlg::SetPickTarget(IPickTarget* pPickTarget)
{
    DBG_WARN_AND_RETURN_VOID_UNLESS(pPickTarget, L"pPickTarget为空",L"GDMP",L"2023-12-30");
    for (int i = 0; i < m_pickTargetNodeGroup->childCount(); i++)
    {
        QTreeWidgetItem* item = m_pickTargetNodeGroup->child(i);
        DBG_WARN_AND_RETURN_VOID_UNLESS(item, L"item为空",L"GDMP",L"2023-12-30");
        std::wstring itemText = item->text(0).toStdWString();
        auto itor = m_pickTargetMap.find(itemText);
        if (itor != m_pickTargetMap.end())
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(itor->second, L"itor为空",L"GDMP",L"2023-12-30");
            itor->second(pPickTarget, item->checkState(0) == Qt::Checked);
        }
    }
}

void Sample::PickFilterDlg::SetPickNodeReferenceOption(PickNodeReferenceOption & pickNodeReferenceOption)
{
    for (int i = 0; i < m_pickNodeReferenceOptionNodeGroup->childCount(); i++)
    {
        QTreeWidgetItem* item = m_pickNodeReferenceOptionNodeGroup->child(i);
        DBG_WARN_AND_RETURN_VOID_UNLESS(item, L"item为空",L"GDMP",L"2023-12-30");
        std::wstring itemText = item->text(0).toStdWString();
        auto itor = m_pickNodeReferenceOptionMap.find(itemText);
        if (itor != m_pickNodeReferenceOptionMap.end())
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(itor->second, L"itor为空",L"GDMP",L"2023-12-30");
            itor->second(pickNodeReferenceOption, item->checkState(0) == Qt::Checked);
        }
    }
}

void Sample::PickFilterDlg::SetPickNodeReferenceExchangeData(PickNodeReferenceExchangeData & pickNodeReferenceExchangeData)
{
    for (int i = 0; i < m_pickNodeReferenceExchangeDataNodeGroup->childCount(); i++)
    {
        QTreeWidgetItem* item = m_pickNodeReferenceExchangeDataNodeGroup->child(i);
        DBG_WARN_AND_RETURN_VOID_UNLESS(item, L"item为空",L"GDMP",L"2023-12-30");
        std::wstring itemText = item->text(0).toStdWString();
        auto itor = m_pickNodeReferenceExchangeDataMap.find(itemText);
        if (itor != m_pickNodeReferenceExchangeDataMap.end())
        {
            DBG_WARN_AND_RETURN_VOID_UNLESS(itor->second, L"itor为空",L"GDMP",L"2023-12-30");
            itor->second(pickNodeReferenceExchangeData, item->checkState(0) == Qt::Checked);
        }
    }
}

void Sample::PickFilterDlg::SetPickMethod(PickMethod pickMethod)
{
    if (pickMethod == PickMethod::IPicker)
    {
        m_pickContextNodeGroup->setHidden(false);
        m_pickTargetNodeGroup->setHidden(false);
        m_pickNodeReferenceOptionNodeGroup->setHidden(true);
        m_pickNodeReferenceExchangeDataNodeGroup->setHidden(true);
    }
    else if (pickMethod == PickMethod::PickNodeReferenceAction)
    {
        m_pickContextNodeGroup->setHidden(true);
        m_pickTargetNodeGroup->setHidden(false);
        m_pickNodeReferenceOptionNodeGroup->setHidden(false);
        m_pickNodeReferenceExchangeDataNodeGroup->setHidden(false);
    }
    else
    {
        m_pickContextNodeGroup->setHidden(true);
        m_pickTargetNodeGroup->setHidden(false);
        m_pickNodeReferenceOptionNodeGroup->setHidden(true);
        m_pickNodeReferenceExchangeDataNodeGroup->setHidden(true);
    }
}
#pragma endregion 和拾取相关的逻辑

